#******************************************************************
#
# Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Import('env')
import os
import datetime

target_os = env.get('TARGET_OS')
target_arch = env.get('TARGET_ARCH')
src_dir = env.get('SRC_DIR')
cur_dir = Dir('.').abspath

######################################################################
# Generate iotivity_config.h using presence of headers
######################################################################

config_h_file_path = os.path.join(cur_dir, 'iotivity_config.h')

if (os.path.exists(config_h_file_path)) and (env.GetOption('clean')):
    os.remove(config_h_file_path)

if not os.path.isfile(config_h_file_path) and env.GetOption not in ('clean', 'help'):
    conf = Configure(env.Clone(LIBS=[]))

    config_h_header = '''
/* ****************************************************************************
 * iotivity_config.h - IoTivity platform-specific configuration header.
 *
 * Auto-generated code for the %s %s platform.
 *
 *************************************************************************** */

#ifndef IOTIVITY_CONFIG_H__
#define IOTIVITY_CONFIG_H__

''' % (str(target_os), str(target_arch))

    config_h_body = ''

    config_h_footer = '''

#include "platform_features.h"

#endif // IOTIVITY_CONFIG_H__

'''

    cxx_headers = [
        'fcntl.h',
        'grp.h',
        'in6addr.h',
        'linux/limits.h',
        'memory.h',
        'pwd.h',
        'stdlib.h',
        'string.h',
        'strings.h',
        'sys/ioctl.h',
        'sys/poll.h',
        'sys/select.h',
        'sys/socket.h',
        'sys/stat.h',
        'sys/time.h',
        'sys/types.h',
        'sys/unistd.h',
        'syslog.h',
        'time.h',
        'unistd.h',
        'uuid/uuid.h'
    ]

    cxx_functions = ['strptime']

    if target_os not in ['windows', 'msys_nt']:
        cxx_headers+=['pthread.h', 'arpa/inet.h', 'net/if.h', 'netdb.h', 'netinet/in.h']
    else:
        cxx_headers+=['windows.h', 'winsock2.h', 'ws2tcpip.h']

    def get_define_from_string(header_file):
        header_file_converted = header_file.replace("/", "_").replace(".", "_").upper()
        return "HAVE_" + header_file_converted

    for header_file_name in cxx_headers:
        if conf.CheckCXXHeader(header_file_name):
            config_h_body += "#define %s 1\n\n" % get_define_from_string(
                header_file_name)

    for function_name in cxx_functions:
        if conf.CheckFunc(function_name):
            config_h_body += "#define %s 1\n\n" % get_define_from_string(
                function_name)
    conf.Finish()

    # Generate the file
    if not os.path.exists(cur_dir):
        os.makedirs(cur_dir)
    if os.path.exists(config_h_file_path):
        os.remove(config_h_file_path)
    config_h_file = open(config_h_file_path, "w")
    config_h_file.write(config_h_header + config_h_body + config_h_footer)
    config_h_file.close()


# Sanity check to ensure that the above block created the file.
if (not os.path.exists(config_h_file_path)) and (not env.GetOption('clean')):
    msg = "Error: iotivity_config.h file not created!"
    Exit(msg)

# iotivity_config.h should be copied to installation dir
env.UserInstallTargetHeader(
    config_h_file_path, 'c_common', 'iotivity_config.h')

# Use the generated file internally
env.AppendUnique(CPPPATH=[cur_dir])

######################################################################

env.AppendUnique(CPPPATH=[
    os.path.join(Dir('.').abspath, 'oic_malloc', 'include'),
    os.path.join(Dir('.').abspath, 'oic_string', 'include'),
    os.path.join(Dir('.').abspath, 'oic_time', 'include'),
    os.path.join(Dir('.').abspath, 'ocatomic', 'include'),
    os.path.join(Dir('.').abspath, 'ocrandom', 'include'),
    os.path.join(Dir('.').abspath, 'octhread', 'include'),
    os.path.join(Dir('.').abspath, 'ocevent', 'include'),
    os.path.join(Dir('.').abspath, 'oic_platform', 'include'),
    os.path.join(Dir('.').abspath, 'octimer', 'include'),
    os.path.join(Dir('.').abspath, 'oc_refcounter', 'include'),
    '#/extlibs/mbedtls/mbedtls/include'
])

if target_os not in ['tizen']:
    env.AppendUnique(
        LIBPATH=[os.path.join(env.get('BUILD_DIR'), 'resource', 'c_common')])

if target_os in ['tizen', 'linux']:
    env.ParseConfig("pkg-config --cflags --libs uuid")

common_env = env.Clone()

######################################################################
# Add platform-specific helper library
######################################################################

if target_os in ['windows', 'msys_nt']:
    SConscript('windows/SConscript', 'common_env')

######################################################################
# Source files and Targets
######################################################################
common_src = [
    'oic_string/src/oic_string.c',
    'oic_malloc/src/oic_malloc.c',
    'oic_time/src/oic_time.c',
    'ocrandom/src/ocrandom.c',
    'oic_platform/src/oic_platform.c',
    'oc_refcounter/src/oc_refcounter.c'
]

if env['POSIX_SUPPORTED']:
    common_src.append('octhread/src/posix/octhread.c')
elif target_os in ['windows']:
    common_src.append('octhread/src/windows/octhread.c')
else:
    common_src.append('octhread/src/noop/octhread.c')

if target_os in ['windows', 'msys_nt']:
    common_src.append('ocatomic/src/windows/ocatomic.c')
else:
    common_src.append('ocatomic/src/others/ocatomic.c')

if target_os in ['windows']:
    common_src.append('ocevent/src/windows/ocevent.c')
    common_src.append('oic_platform/src/windows/oic_winplatform.cpp')
else:
    common_src.append('ocevent/src/others/ocevent.c')
    common_src.append('oic_platform/src/others/oic_otherplatforms.c')

common_src.append('octimer/src/octimer.c')

common_env.AppendUnique(LIBS=['logger'])
common_env.AppendUnique(CPPPATH=['#resource/csdk/logger/include'])
commonlib = common_env.StaticLibrary('c_common', common_src)
common_env.InstallTarget(commonlib, 'c_common')
common_env.UserInstallTargetLib(commonlib, 'c_common')

common_env.UserInstallTargetHeader(
    'iotivity_commontypes.h', 'c_common', 'iotivity_commontypes.h')
common_env.UserInstallTargetHeader(
    'iotivity_debug.h', 'c_common', 'iotivity_debug.h')
common_env.UserInstallTargetHeader(
    'ocrandom/include/experimental/ocrandom.h',
    'c_common/experimental', 'ocrandom.h')
common_env.UserInstallTargetHeader(
    'platform_features.h', 'c_common', 'platform_features.h')
common_env.UserInstallTargetHeader(
    'experimental/byte_array.h', 'c_common/experimental', 'byte_array.h')


Clean(commonlib, config_h_file_path)

# c_common calls into logger.
env.PrependUnique(LIBS=['c_common', 'logger'])
